package com.winit.core.server.linux;

import com.winit.common.util.Constants;
import com.winit.core.server.base.CmdOutputHandler;
import com.winit.core.server.base.ExecResultHandler;
import com.winit.core.server.base.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.*;

/**
 * Created by keel2008 on 16/9/12.
 */
public class LinuxLocalServer implements Server {

    private static final Logger logger = LoggerFactory.getLogger(LinuxLocalServer.class);

    private static final LinuxLocalServer LINUX_LOCAL_SERVER = new LinuxLocalServer();

    private LinuxLocalServer() {
    }

    public static LinuxLocalServer getInstance() throws Exception {
        return LINUX_LOCAL_SERVER;
    }

    public ExecResultHandler doExecRtnHandler(String... cmd) throws Exception {
        ExecResultHandler handler = new ExecResultHandler();
        this.doExec(handler, cmd);
        return handler;
    }

    @Override
    public void doExec(String... cmd) throws Exception {
        ExecResultHandler handler = new ExecResultHandler();
        this.doExec(handler, cmd);
    }

    /**
     * 本地执行shell命令
     * @param handler
     * @param cmd 一次性同时执行的多个命令  例如要执行"cd /usr && mkdir aa" 传入参数为:"cd /usr","mkdir aa"
     *            方法在运行完cd命令后 会继续运行mkdir命令  如果cd命令运行失败则退出
     * @throws Exception
     */
    @Override
    public void doExec(CmdOutputHandler handler, String... cmd) throws Exception {
        StringBuffer command = new StringBuffer();
        for (int i = 0; i < cmd.length; i++) {
            command.append(cmd[i]).append("##");
        }

        String[] param = new String[3];
        param[0] = "bash";
        param[1] = Constants.SHELL_PATH+"shell/beetle_run_shell.sh";
        param[2] = command.toString();

        this.runShell(param,handler);

    }

    private String runShell(String[] param,CmdOutputHandler handler){
        StringBuffer str = new StringBuffer();
        try {
            Process process = Runtime.getRuntime().exec(param);
            BufferedInputStream in = new BufferedInputStream(process.getInputStream());
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line=br.readLine()) != null ) {
                if(line.startsWith("error")){
                    handler.onMessage(line.split("#")[2],Integer.parseInt(line.split("#")[1]),"",true);
                }else if(line.startsWith("success")){
                    handler.onMessage(line.split("#")[2],Integer.parseInt(line.split("#")[1]),"",false);
                }else {
                    handler.onMessage("",0,line,!isSuccess(line));
                }
            }
            br.close();
            in.close();
        } catch (IOException e) {
            handler.onMessage("",0,e.getMessage(),true);
        }
        return str.toString();
    }

    /**
     * 根据黑名单的字符串,判断一段输出是否意味着执行结果是错误的.
     * 
     * @param desc
     * @return
     */
    private boolean isSuccess(String desc){

        if(StringUtils.isEmpty(desc)){
            return true;
        }

        if(desc.contains("No such file or directory")){
            return false;
        }else if(desc.contains("command not found")){
            return false;
        }
        return true;
    }

    public void writeLogFile(String msg, String logFilePath, boolean useTime) throws Exception {
        if(StringUtils.isEmpty(msg)){
            return;
        }
        File file = new File(logFilePath);
        if (file.isDirectory() || !file.getParentFile().exists()) {
            logger.warn("向指定文件输出日志,文件路径不正确.path=" + logFilePath);
        }
        if (useTime) {
            this.doExec("echo `date +%Y:%m:%d-%H:%M:%S` '"+msg+"' >> "+logFilePath);
        }else {
            this.doExec("echo '"+msg+"' >> "+logFilePath);
        }
    }
}
